#ifndef TRACKER_KCF_H
#define TRACKER_KCF_H

#include <string>
#include <memory>
// opencv
#include <opencv2/core/core.hpp>

using namespace std;

namespace handtrack {

class TrackerKCF
{
public:
    typedef shared_ptr<TrackerKCF> Ptr;

    TrackerKCF(int patch_size = 96, bool multiscale = true);

    ~TrackerKCF();

    // Update tracker based on the object's ROI and new frame data
    void update(const cv::Rect& src_roi, cv::Mat src_image, float train_interp_factor);

    // Detect object in the current frame
    cv::Rect detect(const cv::Rect& dst_roi, cv::Mat dst_image, float& peak_value);

protected:
    cv::Point2f findPixelPeak(cv::Mat z, cv::Mat x, float& peak_value);

    void adjustROI(const cv::Rect& roi, cv::Mat image);

    // Evaluates a Gaussian kernel with bandwidth SIGMA for all relative shifts between input images X and Y,
    // which must both be MxN. They must also be periodic (ie., pre-processed with a cosine window).
    cv::Mat gaussianCorrelation(cv::Mat x1, cv::Mat x2);

    // Obtain sub-window from image, with replication-padding and extract features.
    cv::Mat getFeatures(const cv::Mat& image, float scale_adjust = 1.f);

    // Calculate sub-pixel peak for one dimension.
    float subPixelPeak(float left, float center, float right);

    // Initialize Hanning window. Function called only in TrackerKCF constructor.
    void createHanningMats();

    // Create Gaussian Peak. Function called only in TrackerKCF constructor.
    void createGaussianPeak();

    cv::Mat _alphaf;
    cv::Mat _tmpl;
    cv::Mat _prob;
    cv::Mat _hann;
    cv::Rect_<float> _roi;
    cv::Rect_<float> _pad_roi;
    int _patch_size;
    float _sigma;
    float _output_sigma_factor;
    float _lambda;
    float _padding;
    float _scale;
    float _scale_step;
    float _scale_weight;
};

} // end namespace handtrack

#endif // TRACKER_KCF_H